package com.ruicar.afs.cloud.afscase.common.utils;

import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruicar.afs.cloud.afscase.approveocr.entity.ApproveOcrBatch;
import com.ruicar.afs.cloud.afscase.approvetask.entity.*;
import com.ruicar.afs.cloud.afscase.approvetask.vo.WorkflowAppointVO;
import com.ruicar.afs.cloud.afscase.common.step.ServiceBox;
import com.ruicar.afs.cloud.afscase.common.step.StepInvoker;
import com.ruicar.afs.cloud.afscase.common.step.StepParam;
import com.ruicar.afs.cloud.afscase.common.step.Steps;
import com.ruicar.afs.cloud.afscase.infomanagement.entity.CaseBaseInfo;
import com.ruicar.afs.cloud.afscase.infomanagement.service.CaseBaseInfoService;
import com.ruicar.afs.cloud.afscase.processor.enums.NormalSubmitType;
import com.ruicar.afs.cloud.afscase.processor.enums.WorkflowType;
import com.ruicar.afs.cloud.afscase.processor.vo.NormalTaskSubmitVO;
import com.ruicar.afs.cloud.afscase.remind.entity.CaseRemindDetail;
import com.ruicar.afs.cloud.afscase.step.entity.CaseStepParam;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.util.SpringContextHolder;
import com.ruicar.afs.cloud.common.modules.afscorebusiness.enums.*;
import com.ruicar.afs.cloud.risk.api.enums.tortoise.GwtTortoiseStartApproveType;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @Description
 * @Author Peng_Jinbo
 * @Date 2020/06/23 14:15
 */

@UtilityClass
@Slf4j
public class StepUtil {

    final ServiceBox serviceBox;

    static {
        serviceBox = SpringContextHolder.getBean(ServiceBox.class);
    }

    /**
     * @Description 分单前置步骤执行，影像件ocr识别 -> 玄武大数据 -> 自动打标签
     * @Author Peng_Jinbo
     * @Date 2020/6/24 9:31
     */
    public void prevSteps(StepParam stepParams) {
        // 流程退回、经销商流程内撤回时跳过ocr
        final Integer jumpOverOCR = 1;
        CaseBaseInfoService caseBaseInfoService = serviceBox.getCaseBaseInfoService();
        if (Objects.isNull(stepParams.getBaseInfo())) {
            CaseBaseInfo caseBaseInfo = caseBaseInfoService.getOne(Wrappers.<CaseBaseInfo>lambdaQuery().eq(CaseBaseInfo::getApplyNo, stepParams.getApplyNo()));
            stepParams.setBaseInfo(caseBaseInfo);
        }
        Integer startStep = Objects.isNull(stepParams.getProcessTypeEnum()) || stepParams.isTortoiseNoticeBack() || stepParams.isCallBackSubmit()
                ? Convert.toInt(stepParams.getBaseInfo().getWorkflowPrevStep(), 0)
                : jumpOverOCR;

        Steps.create()
                .then(ocr())
                .then(credit())
                .then(title())
                .then(dayBookResolve())
                .err(prevStepErr())
                .end(prevStepEnd())
                .doStep(stepParams, startStep);
    }


    /**
     * @Description ocr影像识别
     * @Author Peng_Jinbo
     * @Date 2020/7/8 17:30
     */
    private static StepInvoker ocr() {
        return (stepParam, currentStep) -> {
            log.info("{}:自动执行ocr识别开始...", stepParam.getApplyNo());
            // 流程退回再提交时不再进行ocr识别
            if (stepParam.isReturnSubmit()) {
                log.info("{}:流程退回提交，跳过ocr自动识别...", stepParam.getApplyNo());
                return true;
            }
            // 流程撤回再提交时不再进行ocr识别
            if (stepParam.isCallBackSubmit()) {
                log.info("{}:流程撤回(废弃)后提交，跳过ocr自动识别...", stepParam.getApplyNo());
                return true;
            }
            CaseBaseInfo baseInfo = stepParam.getBaseInfo();
            if (WhetherEnum.YES.getCode().equals(baseInfo.getAutomaticTag())) {  // 电子授权
                stepParam.getBaseInfo().setBusinessStateIn(AfsEnumUtil.key(BusinessStateInEnum.WAIT_QUERY));
                stepParam.getBaseInfo().setWorkflowPrevStep(currentStep);
                serviceBox.getCaseBaseInfoService().updateById(stepParam.getBaseInfo());
                return true;
            } else { // 纸质授权
                try {
                    int existsCount = serviceBox.getApproveOcrBatchService().count(
                            Wrappers.<ApproveOcrBatch>lambdaQuery()
                                .eq(ApproveOcrBatch::getApplyNo,stepParam.getApplyNo())
                    );
                    ApproveOcrBatch ocrBatch = new ApproveOcrBatch();
                    ocrBatch.setApplyNo(stepParam.getApplyNo());
                    ocrBatch.setOcrResult(WhetherEnum.NO.getCode());
                    ocrBatch.setDisposeResult(WhetherEnum.NO.getCode());
                    ocrBatch.setUseScene(UseSceneEnum.AUTO_OCR.getValue());
                    serviceBox.getApproveOcrBatchService().save(ocrBatch);
                    if(existsCount > 0){ // 退回重提的情况记录进入人工签名确认队列时间
                        serviceBox.getCaseApproveRecordService().repeatIntoOcr(ocrBatch);
                        // 案件状态置为已提交
                        serviceBox.getCaseBaseInfoService().update(
                                Wrappers.<CaseBaseInfo>lambdaUpdate()
                                    .eq(CaseBaseInfo::getApplyNo,stepParam.getApplyNo())
                                    .set(CaseBaseInfo::getBusinessStateIn,AfsEnumUtil.key(BusinessStateInEnum.SUBMITTED))
                        );
                    }
                    stepParam.setStillAddStep(true);
                } catch (Exception e) {
                    log.error("纸质授权案件批次信息录入异常.", e);
                } finally {
                    return false;
                }
            }
        };
    }

    /**
     * @Description 自动打标签
     * @Author Peng_Jinbo
     * @Date 2020/7/8 17:30
     */
    private static StepInvoker title() {
        return (stepParam, currentStep) -> {
            try {
                log.info("{}:自动打标签开始执行...", stepParam.getApplyNo());
                serviceBox.getManualLabelService().transmitDataForLabel(stepParam.getApplyNo());
                if (!stepParam.isReturnSubmit() && Objects.isNull(stepParam.getProcessTypeEnum())) {
                    stepParam.getBaseInfo().setWorkflowPrevStep(currentStep);
                    serviceBox.getCaseBaseInfoService().updateById(stepParam.getBaseInfo());
                }
                return true;
            } catch (Exception e) {
                log.error("自动打标签执行失败.", e);
                return false;
            }
        };
    }

    /**
     * @Description 玄武大数据
     * @Author Peng_Jinbo
     * @Date 2020/7/8 17:30
     */
    private static StepInvoker credit() {
        return (stepParam, currentStep) -> {
            log.info("{}：自动执行玄武征信...", stepParam.getApplyNo());
            if (serviceBox.getCaseConfParamService().checkSwitch(Const.PARAMS_SWITCH_XUANWU)) {
                // 001 场景调用区分复议
                GwtTortoiseStartApproveType approveType = GwtTortoiseStartApproveType.NORMAL;
                if(stepParam.getProcessTypeEnum() == ProcessTypeEnum.FORMAL_REVIEW){
                       approveType = GwtTortoiseStartApproveType.REVIEW;
                }
                serviceBox.getCaseTortoiseService().signalApply(stepParam.getApplyNo(),approveType);
                stepParam.getBaseInfo().setTortoiseApplyExecute(AfsEnumUtil.key(TortoiseApplyExecuteEnum.PROCESSING));
                stepParam.setStillAddStep(true);
                return false;
            } else {
                log.info("信审：{}：玄武征信接口开关[{}]未配置或已关闭，取消调用，跳过当前步骤", stepParam.getApplyNo(),Const.PARAMS_SWITCH_XUANWU);
                return true;
            }
        };
    }

    /**
     * @Description 获取流水解析/同盾报告/车e估车辆评估报告
     * @Author Peng_Jinbo
     * @Date 2020/8/31 18:31
     */
    private static StepInvoker dayBookResolve() {
        return (stepParam, currentStep) -> {
            try {
                serviceBox.getDayBookResolveService().getDayBookResolve(stepParam.getApplyNo());
                serviceBox.getCaseTortoiseService().downloadTdReport(stepParam.getApplyNo());
                serviceBox.getCaseTortoiseService().downloadECarReport(stepParam.getApplyNo());
            } catch (Exception e) {
                log.error("流水解析失败/同盾报告/车e估车辆评估报告", e);
            } finally {
                return true;
            }
        };
    }

    /**
     * @Description 分单前置错误处理
     * @Author Peng_Jinbo
     * @Date 2020/7/8 17:30
     */
    private static StepInvoker prevStepErr() {
        return (stepParam, currentStep) -> {
            log.info("{}:执行错误，当前步骤执行至 " + currentStep, stepParam.getApplyNo());
            CaseBaseInfo baseInfo = stepParam.getBaseInfo();
            baseInfo.setWorkflowPrevStep(currentStep);
            serviceBox.getCaseBaseInfoService().updateById(baseInfo);
            return true;
        };
    }

    /**
     * @Description 正常结束处理
     * @Author Peng_Jinbo
     * @Date 2020/7/8 17:31
     */
    private static StepInvoker prevStepEnd() {
        return (stepParam, endStep) -> {
            log.info("{}:自动分单前置逻辑执行完毕...", stepParam.getApplyNo());
            // 复议首次提交
            if(ProcessTypeEnum.FORMAL_REVIEW == stepParam.getProcessTypeEnum() && !stepParam.isReturnSubmit()){
                log.info("正式复议流程发起！！！");
                makeWorkStart(stepParam);
                serviceBox.getCaseStepParamService().clear(stepParam.getApplyNo(),StepSceneEnum.APPROVE);
                return true;
            // 常规审批流程/复议 修订回复
            }else if ((ProcessTypeEnum.GENERA_APPROVE == stepParam.getProcessTypeEnum()
                        || ProcessTypeEnum.FORMAL_REVIEW == stepParam.getProcessTypeEnum())
                    && stepParam.isReturnSubmit() && !stepParam.isCallBackSubmit()) {
                WorkProcessScheduleInfo info = serviceBox.getWorkProcessScheduleInfoService().getById(stepParam.getStageId());
                WorkTaskPool pool = serviceBox.getWorkTaskPoolService().getOne(
                        Wrappers.<WorkTaskPool>lambdaQuery()
                                .eq(WorkTaskPool::getStageId, stepParam.getStageId())
                );
                CaseApproveRecord record = new CaseApproveRecord();
                record.setStageId(info.getStageId());
                record.setApplyNo(info.getApplyNo());
                record.setApproveSuggest(AfsEnumUtil.key(NormalSubmitType.MODIFY_SUBMIT));
                record.setApproveSuggestName(AfsEnumUtil.desc(NormalSubmitType.MODIFY_SUBMIT));
                record.setDisposeNode(pool.getTaskNodeId());
                record.setDisposeNodeName(pool.getTaskNodeName());
                record.setApproveStartTime(pool.getStartTime());
                record.setApproveEndTime(new Date());
                record.setApproveType(ApproveTypeEnum.PROCESS.getValue());
                record.setDisposeStaff(pool.getApproveStaffName());
                record.setApproveRemark(stepParam.getLeaveMessage());
                serviceBox.getApproveWorkflowService().submit(NormalTaskSubmitVO.builder().workFlowInfo(info).workTaskPool(pool).record(record).build());

                /**
                 * 修订回复添加留言
                 */
                if(StringUtils.isNotBlank(stepParam.getLeaveMessage())){
                    //留言
                    CaseRemindDetail remindDetail =new CaseRemindDetail();
                    remindDetail.setApplyNo(stepParam.getApplyNo());
                    remindDetail.setDisposeUser(pool.getApproveStaffName());
                    remindDetail.setStatus(CancelStatusEnum.EFFECTIVE.getCode());
                    remindDetail.setDisposeTime(new Date());
                    remindDetail.setUseScene(UseSceneEnum.APPROVE.getValue());
                    remindDetail.setRemindContent(stepParam.getLeaveMessage());
                    serviceBox.getRemindService().save(remindDetail);
                }

                serviceBox.getCaseStepParamService().clear(stepParam.getApplyNo(),StepSceneEnum.APPROVE);
                return true;
            } else {
                // 流程发起前提交
                // 通知进件端状态改为待审核
                CaseApproveRecord record = new CaseApproveRecord();
                record.setApplyNo(stepParam.getApplyNo());
                record.setApproveStartTime(new Date());
                record.setApproveSuggest(SendApproveTypeEnum.PENDING_REVIEW.getCode());
                serviceBox.getApproveInformInfoService().submitApprovalNotic(record);

                CaseBaseInfo baseInfo = stepParam.getBaseInfo();
                baseInfo.setBusinessStateIn(AfsEnumUtil.key(BusinessStateInEnum.ALLOCATION));
                baseInfo.setWorkflowPrevStep(endStep);
                serviceBox.getCaseBaseInfoService().updateById(baseInfo);
                serviceBox.getCaseStepParamService().clear(stepParam.getApplyNo(),StepSceneEnum.APPROVE);
                return true;
            }
        };
    }

    private  static void makeWorkStart(StepParam stepParam) {
        CaseBaseInfo baseInfo = serviceBox.getCaseBaseInfoService().getOne(Wrappers.<CaseBaseInfo>query().lambda()
                .eq(CaseBaseInfo::getApplyNo, stepParam.getApplyNo()));
        List<WorkTaskPoolHistory> hisList = serviceBox.getHistoryService().list(Wrappers.<WorkTaskPoolHistory>query().lambda()
                .eq(WorkTaskPoolHistory::getStageId, baseInfo.getNormalApproveFlowId())
                .eq(WorkTaskPoolHistory::getFirstNode, WhetherEnum.YES.getCode())
                .orderByDesc(WorkTaskPoolHistory::getCreateTime));
        //发起正式流程
        WorkflowAppointVO appointVO = new WorkflowAppointVO();
        if (CollectionUtils.isNotEmpty(hisList)) {
            log.info("正式复议流程发起当前指定人:{}",hisList.get(0).getApproveStaff());
            WorkProcessScheduleInfoTemp temp = new WorkProcessScheduleInfoTemp();
            temp.setAfsFlowKey(WorkflowType.FORMAL_REVIEW.getAfsFlowKey());
            temp.setApplyNo(stepParam.getApplyNo());
            temp.setAppointHandler(hisList.get(0).getApproveStaff());
            serviceBox.getScheduleInfoTempService().saveWithNewTransactional(temp);

            appointVO.setApplyNo(stepParam.getApplyNo());
            appointVO.setAppointStaff(hisList.get(0).getApproveStaff());
            serviceBox.getWorkflowService().start(temp);
            log.info("正式复议流程发起完成！！！");
        }
    }
}
